package org.bdware.irs.irp.handle;

import com.google.gson.Gson;
import org.bdware.irs.backend.dto.Organization;
import org.bdware.irs.backend.servicesImpl.BDGrsStorageRocksDBImpl;
import org.apache.log4j.Logger;
import org.bdware.irp.irplib.core.IrpMessage;
import org.bdware.irp.irplib.core.IrpMessageCode;
import org.bdware.irp.irplib.core.IrpRequest;
import org.bdware.irp.irplib.core.IrpResponse;
import org.bdware.irp.irplib.util.GlobalUtils;
import org.bdware.irp.irpserver.GrsHandler;
import org.bdware.irp.irpserver.IrpServerInfo;
import org.bdware.irp.stateinfo.StateInfoBase;

import java.util.Map;


public class GrsHandlerImpl implements GrsHandler {
    Logger logger = Logger.getLogger(GrsHandlerImpl.class);
    IrpServerInfo serverInfo;
    BDGrsStorageRocksDBImpl store;

    public GrsHandlerImpl(IrpServerInfo info, BDGrsStorageRocksDBImpl store){
        serverInfo = info;
        this.store = store;
    }

    @Override
    public IrpMessage verifyIRS (IrpMessage request){
        IrpRequest req = (IrpRequest) request;

        Organization organization = store.getOrganization(req.getDoid());
        String pkInfo = organization.getJwkKey();
        //get the pk from the database
        boolean result = GlobalUtils.verifySigByJWK(req.encodedMessageBody, req.getSignature(), pkInfo);

        IrpMessage res;
        if(result == true) {
            organization.setServiceAddress(req.getAddress());
            store.updateOrganization(organization);
            logger.debug("Verify irs success: " + req.getDoid());
            res = IrpResponse.newVerifyIrsResponse(req.getDoid(), "verity success!");

        }else {
            logger.debug("Verify irsd failed: " + req.getDoid());
            res = IrpResponse.newErrorResponse(
                    IrpMessageCode.OC_VERIFY_IRS,
                    IrpMessageCode.RC_ERROR,
                    "Verify irs error!");
        }
        return res;
    }

    @Override
    public IrpMessage doidResolve(IrpMessage request) {
        IrpRequest req = (IrpRequest) request;

        Organization organization = store.getOrganization(req.getDoid());

        IrpMessage res;

        if(organization != null) {
            logger.debug("Resolve doid success: " + req.getDoid());
            StateInfoBase stateInfoBase = organization.toStateInfoBase();
            Map<String, String> values = new Gson().fromJson(stateInfoBase.getHandleValues(), Map.class);
            res = IrpResponse.newIrsResolveResponse(req.getDoid(), values);
        }else {
            logger.debug("Resolve doid failed: " + req.getDoid());
            res = IrpResponse.newErrorResponse(
                    IrpMessageCode.OC_RESOLUTION_DOID,
                    IrpMessageCode.RC_ERROR,
                    "resolve doid error!");
        }
        return res;
    }


    @Override
    public IrpMessage createOrg(IrpMessage request){
        IrpRequest req = (IrpRequest) request;
        logger.info(new Gson().toJson(req));
        StateInfoBase stateInfoBase = IrsHandlerImpl.request2StateInfo(req.getDoid(), req.getDoidValuesByMap());
        logger.info(new Gson().toJson(stateInfoBase));

        boolean verifyResult = true;

        IrpMessage res;
        if(verifyResult == true){
            boolean result = store.saveOrganization(Organization.fromStateInfoBase(stateInfoBase));
            if(result) {
                logger.debug("save org success");
                res = IrpResponse.newOrgCreateResponse(stateInfoBase.getIdentifier());
            }else {
                logger.debug("Create org failed!");
                res = IrpResponse.newErrorResponse(IrpMessageCode.OC_CREATE_ORG_GRS, IrpMessageCode.RC_ERROR,
                        "Create org error!");
            }
        }else{
            logger.debug("Auth the user failed!");
            res = IrpResponse.newErrorResponse(IrpMessageCode.OC_CREATE_ORG_GRS, IrpMessageCode.RC_ERROR,
                    "Auth the user failed!");
        }
        return res;
    }

    @Override
    public IrpMessage updateOrg(IrpMessage request) {
        IrpRequest req = (IrpRequest) request;
        StateInfoBase stateInfoBase = IrsHandlerImpl.request2StateInfo(req.getDoid(), req.getDoidValuesByMap());
        boolean verifyResult = true;

        IrpMessage res;
        if(verifyResult == true){
            boolean result = store.updateOrganization(Organization.fromStateInfoBase(stateInfoBase));
            if(result) {
                logger.debug("update org success");
                res = IrpResponse.newOrgUpdateResponse(stateInfoBase.getIdentifier());
            }else {
                logger.debug("update org failed!");
                res = IrpResponse.newErrorResponse(IrpMessageCode.OC_UPDATE_ORG_GRS, IrpMessageCode.RC_ERROR,
                        "Create org error!");
            }
        }else{
            logger.debug("Auth the user failed!");
            res = IrpResponse.newErrorResponse(IrpMessageCode.OC_UPDATE_ORG_GRS, IrpMessageCode.RC_ERROR,
                    "Auth the user failed!");
        }
        return res;
    }

    @Override
    public IrpMessage deleteOrg(IrpMessage request) {
        IrpRequest req = (IrpRequest) request;
        StateInfoBase stateInfoBase = IrsHandlerImpl.request2StateInfo(req.getDoid(), req.getDoidValuesByMap());
        boolean verifyResult = true;

        IrpMessage res;
        if(verifyResult == true){
            boolean result = store.deleteOrganization(Organization.fromStateInfoBase(stateInfoBase));
            if(result) {
                logger.debug("delete org success");
                res = IrpResponse.newOrgDeleteResponse(stateInfoBase.getIdentifier());
            }else {
                logger.debug("delete org failed!");
                res = IrpResponse.newErrorResponse(IrpMessageCode.OC_DELETE_ORG_GRS, IrpMessageCode.RC_ERROR,
                        "delete org error!");
            }
        }else{
            logger.debug("Auth the user failed!");
            res = IrpResponse.newErrorResponse(IrpMessageCode.OC_DELETE_ORG_GRS, IrpMessageCode.RC_ERROR,
                    "Auth the user failed!");
        }
        return res;
    }

}
